18

正则表达式及多语言操作指南

1. 正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,模式描述在搜索文本时要匹配的一个或多个字符串。

1.1 正则表达式符号

1.1.1 符号类

通用的符号:

符号 含义 范例
. 任意字符 “A”, “ ”(空格), “囧”, “1”
d 匹配一个数字字符。等价于[0-9] “1”, “2”, “3”
D 匹配一个非数字字符。等价于[^0-9] “a”, “b”, “c”
w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]” “Y”, “x”, “_”, “9”
W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]” “ ”(空格)
s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ fnrtv] “ ”(空格), “r”, “t”, “n”
S 匹配任何非空白字符。等价于[^fnrtv] “B”, “囧”, “5”

特殊的符号:

符号 含义 范例
r 匹配一个回车符。等价于x0d和cM
f 匹配一个换页符。等价于x0c和cL
n 匹配一个换行符。等价于x0a和cJ
t 匹配一个制表符。等价于x09和cI
\\ 匹配 “”
xhh 以ASCII码进⾏匹配 x41可以匹配”A”
uhhhh 以UNICODE码进⾏匹配 u4e00-u9fa5 中⽂的范围

重点:关于 .

单行模式下(gs):能匹配\n
多行模式下(gm):不能匹配 \n

1.1.2 字符集合

符号 含义
[a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符
[abc] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”
[^xyz] 负值字符集合。匹配未包含的任意字符。例如,“1”可以匹配“plain”中的“p”
[^a-c] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“2”可以匹配任何不在“a”到“z”范围内的任意字符
[\-] 匹配 “-”

1.1.3 字符边界

符号 含义
^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“n”或“r”之后的位置
& 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“n”或“r”之前的位置
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如,“erb”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”
\B 匹配非单词边界。“erB”能匹配“verb”中的“er”,但不能匹配“never”中的“er”

1.1.4 数量界定符

符号 定义
x{n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o
x{n,} n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”
x{n,m} m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格
x* 匹配前面的子表达式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}
x+ 匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}
x? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}

重点:关于 ?

贪婪模式下:数量限定符都是在满⾜条件下尽可能的匹配更多的字符
非贪婪模式下:如果希望在满⾜条件下尽可能少的匹配字符, 在数量限定符后⾯加上“?”

1.1.5 分支条件

符号 定义
x\ y 匹配x或y。例如,“z\ food”能匹配“z”或“food”。“(z\ f)ood”则匹配“zood”或“food”。

1.1.6 分组与后向引⽤

符号 定义
(x) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”
1..n 引⽤第1-n组匹配
(?:x) 匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“( )”来组合一个模式的各个部分是很有用。例如“industr(?:y ies)”就是一个比“industry industries”更简略的表达式

1.1.7 断⾔

符号 定义
(?=pattern) 正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95 98 NT 2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
(?!pattern) 正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95 98 NT 2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
(?<=pattern) 反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95 98 NT 2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”
(?<!pattern) 反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95 98 NT 2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”

1.2 正则表达式网站

以下是常用的一些在线正则表达式测试工具,其中个人感觉第一个最好!

  1. http://regex101.com/
  2. http://regexr.com/
  3. http://tool.lu/regex/
  4. http://tool.oschina.net/regex/
  5. http://tool.chinaz.com/regex/

1.3 正则表达式工具

  1. RegexBuddy
  2. RegexMagic

1.4 常用的正则表达式

需求 正则表达式
用户名 ^[a-z0-9_-]{3,16}$
密码 ^[a-z0-9_-]{6,18}$
十六进制值 ^#?([a-f0-9]{6} [a-f0-9]{3})$
电子邮箱 ^([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})$/
URL ^(https?://)?([da-z.-]+).([a-z.]{2,6})([/w .-]*)*/?$
IP 地址 /((2[0-4]d 25[0-5] [01]?dd?).){3}(2[0-4]d 25[0-5] [01]?dd?)/
/^(?:(?:25[0-5] 20-4 [01]?0-9?).){3}(?:25[0-5] 20-4 [01]?0-9?)$/</div>
HTML 标签 ^<([a-z]+)([^<]+)*(?:>(.*)</1> s+/>)$
删除代码\注释 (?<!http: S)//.*$
Unicode编码中的汉字范围 ^[u2E80-u9FFF]+$
一个单词连续出现的位置 b([a-z]+) 1b/gi
匹配空行 ^s*$
匹配中文字符 [u4e00-u9fa5]
匹配双字节字符(包括汉字在内) [^x00-xff]
匹配空白行 ns*r
匹配国内电话号码 d{3}-d{8} d{4}-{7,8}
匹配腾讯QQ号 1-9{4,}
匹配中国邮政编码 [1-9]d{5}(?!d)
匹配18位身份证号 ^(d{6})(d{4})(d{2})(d{2})(d{3})([0-9] X)$
匹配(年-月-日)格式日期 ([0-9]{3}[1-9]
匹配正浮点数 ^[1-9]d*.d* 0.d*[1-9]d*$
匹配负浮点数 ^-[1-9]d*.d* -0.d*[1-9]d*$

2. Python操作正则表达式

参考文献:https://www.liaoxuefeng.com/w...

2.1 匹配字符串

Python提供re模块,包含所有正则表达式的功能。由于Python的字符串本身也用\转义,所以要特别注意:

s = 'ABC\\-001' # Python的字符串
# 对应的正则表达式字符串变成:
# 'ABC\-001'

因此我们强烈建议使用Python的r前缀,就不用考虑转义的问题了:

s = r'ABC\-001' # Python的字符串
# 对应的正则表达式字符串不变:
# 'ABC\-001'

先看看如何判断正则表达式是否匹配:

>>> import re
>>> re.match(r'^\d{3}\-\d{3,8}$', '010-12345')
<_sre.SRE_Match object; span=(0, 9), match='010-12345'>
>>> re.match(r'^\d{3}\-\d{3,8}$', '010 12345')
>>>

match()方法判断是否匹配,如果匹配成功,返回一个Match对象,否则返回None。常见的判断方法就是:

test = '用户输入的字符串'
if re.match(r'正则表达式', test):
    print('ok')
else:
    print('failed')

2.2 切分字符串

用正则表达式切分字符串比用固定的字符更灵活,请看正常的切分代码:

>>> 'a b   c'.split(' ')
['a', 'b', '', '', 'c']

嗯,无法识别连续的空格,用正则表达式试试:

>>> re.split(r'\s+', 'a b   c')
['a', 'b', 'c']

无论多少个空格都可以正常分割。加入,试试:

>>> re.split(r'[\s\,]+', 'a,b, c  d')
['a', 'b', 'c', 'd']

再加入;试试:

>>> re.split(r'[\s\,\;]+', 'a,b;; c  d')
['a', 'b', 'c', 'd']

如果用户输入了一组标签,下次记得用正则表达式来把不规范的输入转化成正确的数组。

2.3 分组

除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组(Group)。比如:

^(\d{3})-(\d{3,8})$分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码:

>>> m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
>>> m
<_sre.SRE_Match object; span=(0, 9), match='010-12345'>
>>> m.group(0)
'010-12345'
>>> m.group(1)
'010'
>>> m.group(2)
'12345'

如果正则表达式中定义了组,就可以在Match对象上用group()方法提取出子串来。

注意到group(0)永远是原始字符串,group(1)group(2)……表示第1、2、……个子串。

提取子串非常有用。来看一个更凶残的例子:

>>> t = '19:05:30'
>>> m = re.match(r'^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$', t)
>>> m.groups()
('19', '05', '30')

这个正则表达式可以直接识别合法的时间。但是有些时候,用正则表达式也无法做到完全验证,比如识别日期:

'^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$'

对于'2-30''4-31'这样的非法日期,用正则还是识别不了,或者说写出来非常困难,这时就需要程序配合识别了。

2.4 贪婪匹配

最后需要特别指出的是,正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。举例如下,匹配出数字后面的0

>>> re.match(r'^(\d+)(0*)$', '102300').groups()
('102300', '')

由于\d+采用贪婪匹配,直接把后面的0全部匹配了,结果0*只能匹配空字符串了。

必须让\d+采用非贪婪匹配(也就是尽可能少匹配),才能把后面的0匹配出来,加个?就可以让\d+采用非贪婪匹配:

>>> re.match(r'^(\d+?)(0*)$', '102300').groups()
('1023', '00')

2.5 编译

当我们在Python中使用正则表达式时,re模块内部会干两件事情:

  1. 编译正则表达式,如果正则表达式的字符串本身不合法,会报错;
  2. 用编译后的正则表达式去匹配字符串。

如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配:

>>> import re
# 编译:
>>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
# 使用:
>>> re_telephone.match('010-12345').groups()
('010', '12345')
>>> re_telephone.match('010-8086').groups()
('010', '8086')

编译后生成Regular Expression对象,由于该对象自己包含了正则表达式,所以调用对应的方法时不用给出正则字符串。

3. Java操作正则表达式

参考文献:http://www.runoob.com/java/ja...

3.1 基础

Java提供了java.util.regex 包来操作正则表达式,主要包含以下三个类:

  1. Pattern 类:pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
  2. Matcher 类:Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
  3. PatternSyntaxException:PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。

以下实例中使用了正则表达式 .*runoob.* 用于查找字符串中是否包了 runoob 子串:

import java.util.regex.*;
 
class RegexExample1{
   public static void main(String args[]){
      String content = "I am noob " +
        "from runoob.com.";
 
      String pattern = ".*runoob.*";
 
      boolean isMatch = Pattern.matches(pattern, content);
      System.out.println("字符串中是否包含了 'runoob' 子字符串? " + isMatch);
   }
}

输出:

字符串中是否包含了 'runoob' 子字符串? true

3.2 捕获组

捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。
例如,正则表达式 (dog) 创建了单一分组,组里包含"d","o",和"g"。
捕获组是通过从左至右计算其开括号来编号。例如,在表达式((A)(B(C))),有四个这样的组:

  1. ((A)(B(C)))
  2. (A)
  3. (B(C))
  4. (C)

可以通过调用 matcher 对象的 groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个 int 值,表示matcher对象当前有多个捕获组。
还有一个特殊的组(group(0)),它总是代表整个表达式。该组不包括在 groupCount 的返回值中。

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    public static void main( String args[] ){
 
      // 按指定模式在字符串查找
      String line = "This order was placed for QT3000! OK?";
      String pattern = "(\\D*)(\\d+)(.*)";
 
      // 创建 Pattern 对象
      Pattern r = Pattern.compile(pattern);
 
      // 现在创建 matcher 对象
      Matcher m = r.matcher(line);
      if (m.find( )) {
         System.out.println("Found value: " + m.group(0) );
         System.out.println("Found value: " + m.group(1) );
         System.out.println("Found value: " + m.group(2) );
         System.out.println("Found value: " + m.group(3) ); 
      } else {
         System.out.println("NO MATCH");
      }
   }
}

输出:

Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT
Found value: 3000
Found value: ! OK?

4. C#操作正则表达式

参考文献:http://www.runoob.com/csharp/...

使用的命名空间 using System.Text.RegularExpressions;

C#中主要使用Regex类来操作正则表达式,其常用的方法如下:

public bool IsMatch( string input )  指示 Regex 构造函数中指定的正则表达式是否在指定的输入字符串中找到匹配项
public bool IsMatch( string input, int startat )  指示 Regex 构造函数中指定的正则表达式是否在指定的输入字符串中找到匹配项,从字符串中指定的开始位置开始
public static bool IsMatch( string input, string pattern )  指示指定的正则表达式是否在指定的输入字符串中找到匹配项
public MatchCollection Matches( string input )  在指定的输入字符串中搜索正则表达式的所有匹配项

<div>public string Replace( string input, string replacement ) </div>

| 在指定的输入字符串中,把所有匹配正则表达式模式的所有匹配的字符串替换为指定的替换字符串 |
| public string[] Split( string input )  | 把输入字符串分割为子字符串数组,根据在 Regex 构造函数中指定的正则表达式模式定义的位置进行分割 |

实例一:下面的实例匹配了以 'S' 开头的单词:

using System;
using System.Text.RegularExpressions;

namespace RegExApplication
{
   class Program
   {
      private static void showMatch(string text, string expr)
      {
         Console.WriteLine("The Expression: " + expr);
         MatchCollection mc = Regex.Matches(text, expr);
         foreach (Match m in mc)
         {
            Console.WriteLine(m);
         }
      }
      static void Main(string[] args)
      {
         string str = "A Thousand Splendid Suns";

         Console.WriteLine("Matching words that start with 'S': ");
         showMatch(str, @"\bS\S*");
         Console.ReadKey();
      }
   }
}

输出:

Matching words that start with 'S':
The Expression: \bS\S*
Splendid
Suns

实例 2: 下面的实例匹配了以 'm' 开头以 'e' 结尾的单词:

using System;
using System.Text.RegularExpressions;

namespace RegExApplication
{
   class Program
   {
      private static void showMatch(string text, string expr)
      {
         Console.WriteLine("The Expression: " + expr);
         MatchCollection mc = Regex.Matches(text, expr);
         foreach (Match m in mc)
         {
            Console.WriteLine(m);
         }
      }
      static void Main(string[] args)
      {
         string str = "make maze and manage to measure it";

         Console.WriteLine("Matching words start with 'm' and ends with 'e':");
         showMatch(str, @"\bm\S*e\b");
         Console.ReadKey();
      }
   }
}

输出:

Matching words start with 'm' and ends with 'e':
The Expression: \bm\S*e\b
make
maze
manage
measure

实例 3:下面的实例替换掉多余的空格:

using System;
using System.Text.RegularExpressions;

namespace RegExApplication
{
   class Program
   {
      static void Main(string[] args)
      {
         string input = "Hello   World   ";
         string pattern = "\\s+";
         string replacement = " ";
         Regex rgx = new Regex(pattern);
         string result = rgx.Replace(input, replacement);

         Console.WriteLine("Original String: {0}", input);
         Console.WriteLine("Replacement String: {0}", result);    
         Console.ReadKey();
      }
   }
}

输出:

Original String: Hello   World   
Replacement String: Hello World 

5. C++操作正则表达式

参考文献:https://blog.csdn.net/makenot...

C++里面使用正则表达式一般有三种:C regex,C ++regex,boost regex

实例一:电子邮件

// Regex.cpp : 定义控制台应用程序的入口点。
//
#include <regex>
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;

//电子邮件匹配
bool is_email_valid(const std::string& email)
{
   const regex pattern("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+");
   /****
    const std::regex pattern("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+"); 
   std:: match_results<std::string::const_iterator> result;
   bool valid = std::regex_match(email, result,pattern);
   //此处result参数可有可无,result是一个字符串数组,用来存储正则表达式里面括号的内容。
   if(valid&&(result.length()>0))
  {
      for(int i =0;i<result.length();i++)
      {
          cout<<result[i]<<endl;
      }
    }
   return valid;
}

实例二:IP

bool is_IPAddress_valid(const std::string& ipaddress)
{
    const std::regex pattern("(\\d{1,3}).(\\d{1,3}).(\\d{1,3}).(\\d{1,3})");
    //三位数的都可以,没有设置1-255 的条件
   std:: match_results<std::string::const_iterator> result;
  bool valid = std::regex_match(ipaddress, result, pattern);
  if(valid&&(result.length()>0))
  {
      for(int i =0;i<result.length();i++)
      {
          cout<<result[i]<<endl;
      }
  }
  return valid;
}

测试:

int main(int argc,char** argv)
{

    cout<<"测试4个电子邮件选项"<<endl;
    std::string email1 = "marius.bancila@domain.com";
    std::string email2 = "mariusbancila@domain.com";
    std::string email3 = "marius_b@domain.co.uk";
    std::string email4 = "marius@domain";

    std::cout << email1 << " : " << (is_email_valid(email1) ? "valid" : "invalid") << std::endl;
    std::cout << email2 << " : " << (is_email_valid(email2) ? "valid" : "invalid") << std::endl;
    std::cout << email3 << " : " << (is_email_valid(email3) ? "valid" : "invalid") << std::endl;
    std::cout << email4 << " : " << (is_email_valid(email4) ? "valid" : "invalid") << std::endl;

    cout<<"测试4个IP地址选项"<<endl;
    std::string IPAddress1 = "202.20.144.3";
    std::string IPAddress2 = "255.02.233.02";
    std::string IPAddress3 = "127.256.2.36";
    std::string IPAddress4 = "123.-25.56.125";

    std::cout << IPAddress1 << " : " << (is_IPAddress_valid(IPAddress1) ? "valid" : "invalid") << std::endl;
    std::cout << IPAddress2 << " : " << (is_IPAddress_valid(IPAddress2) ? "valid" : "invalid") << std::endl;
    std::cout << IPAddress3 << " : " << (is_IPAddress_valid(IPAddress3) ? "valid" : "invalid") << std::endl;
    std::cout << IPAddress4 << " : " << (is_IPAddress_valid(IPAddress4) ? "valid" : "invalid") << std::endl;
    return 0 ;
}

6. Javasript操作正则表达式

参考文献:http://www.runoob.com/js/js-r...
参考文献:https://www.cnblogs.com/zhuzh...

6.1 JavaScript对正则表达式的支持程度

下面的这些都是JavaScript所不支持的:

匹配字符串开始和结尾的A和Z锚。(但我们仍可以使用^和$来匹配字符串的开始和结尾)
向后查找(lookbehind)(注:但是JavaScript完全支持向前查找(lookahead))
并集和交集类
原子组(atomic grouping)
Unicode支持(单个字符除外,如uFFFF)
命名的捕获组
s(single,单行)和x(free-spacing,无间隔)匹配模式
条件匹配
正则表达式注释

6.2 支持正则表达式的RegExp类型

JavaScript是通过RegExp类型来支持正则表达式的。而创建RegExp类型有两种方法。一种是字面量方法(类似于Perl的语法),另一种是使用JavaScript的RegExp构造函数,下面将逐一介绍。

6.2.1 字面量方法
var expression = /pattern/flags;

其中expression即为正则表达式的名称,模式(pattern)可以是任何复杂或简单的正则表达式(但必须是在JavaScript支持范围内的),标志(flags)即用来表明正则表达式行为。

下面介绍JavaScript中支持的三个标志(flags):

  • g: 表示全局(global)模式,表示pattern会应用于所有字符串,而不是找到一个匹配项后立即停止。
  • i :表示不区分大小写(ignore)模式。即忽略pattern和字符串的大小写。
  • m:表示多行(multiple)模式。 即到一行文本末尾时还会继续查找下一行中是否存在匹配的项。

    说明:在字面量方法中的flags可以是g、i、m中的任意一个或几个且这里的标志完全适用于之后要讲的RegExp构造函数方法。

举例:

var pattern=/at/gi;

此字面量形式的正则表达式表示在不区分大小写的情况下在全局范围内匹配at。

6.2.2 RegExp构造函数法
var pattern = new RegExp("pattern","flags");

即这种方法使用了RegExp构造函数,并且传递了两个参数(同字面量方法),但值得注意的是:pattern(模式)和flags(标志)都需要使用引号括起来。

6.2.3 对模式中的元字符转义的方法

当我们希望使用元字符本身的含义时,我们就需要对元字符进行转义。比如[ab]c表示ac或bc;若通过转义,即[ab]c就表示成了[ab]c。但是对于上述两种不同的创建方法有不同的转义方式。

首先,请记住在JavaScript中的元字符有 ( [ { ^ $ | ) ? * + . ] ) }。

使用字面量方法创建正则表达式转义:在需要转义的正则表达式前加即可。如var pattern = /[ab]c/g;表示在全局范围内匹配abc

使用RegExp构造函数创建正则表达式转义:在需要转义的正则表达式前加\。如var pattern = RegExp("\[ab\]c","g");同样表示在全局范围内匹配abc

举例:

如果希望知道字符串XxxxoOoooommmm中o的数量(不区分大小写),这时就可以使用match方法传入字符串,如:

var string = "XxxxoOoooommmm"; console.log(string.match(/o/ig).length);  

输出为6,这种方法还是很容易的。

6.3 RegExp的实例属性

无论是何种方法创建的正则表达式,他们都具有下面几种属性来描述有关模式的信息:

  • global---表示flags(标志)中是否设置了g标志。
  • ignoreCase---表示flags(标志)中是否设置了i标志。
  • lastIndex---表示开始搜索下一个匹配项的字符位置的整数,从0算起。
  • multiple---表示flags(标志)中是否设置了m标志。
  • source---按照字面量形式返回正则表达式的字符串表示。

举例如下所示:

// var pattern = RegExp("\\[ba\\]at","gi");//使用RegExp构造函数创建得到的效果和下面使用的字面量方法创建得到的效果相同
var pattern = /\[ba\]at/gi;
console.log(pattern.global); //true
console.log(pattern.ignoreCase); //true
console.log(pattern.multiline);  //ture
console.log(pattern.lastIndex);  //0 
console.log(pattern.source);  //  \[ba\]at

当然,上面代码中使用了大量的console.log()显得很复杂,也可以将这5个属性作为5个参数直接传入到console.log()中。如下所示:

var pattern = /\[ba\]at/gi;
console.log(pattern.global,pattern.ignoreCase,pattern.multiline,pattern.lastIndex,pattern.source); //true true false 0 "\[ba\]at"

我们还可以将这5个属性保存在一个数组中,再通过console.log()直接输出数组,如下所示:

var pattern = /\[ba\]at/gi;
var properties=[pattern.global,pattern.ignoreCase,pattern.multiline,pattern.lastIndex,pattern.source];
console.log(properties);

6.4 RegExp的实例方法

RegExp的实例主要有两个方法exec()和test(),并且还有从Object继承的toString()和toLocaleString()方法,下面将会逐一介绍。

6.4.1 RegExp实例的exec()方法

这个方法接收一个参数,即要应用模式的字符串,用于捕获组。

如果匹配,则返回一个数组;否则返回null。

且其中返回的数组还有额外的两个方法:index和input。index表示匹配项在字符串中的位置,input表示应用正则表达式的字符串。

举例如下所示:

var text="mom and dad and baby";
    var pattern=/mom( and dad( and baby)?)?/gi;
    var matches=pattern.exec(text);
    console.log(matches);

如果匹配不了,则matches为null;如果匹配,将会在控制台中输出一个数组

6.4.2 RegExp实例的test()方法

这个方法同样也接收一个字符串,如果pattern(模式)和字符串匹配,则返回true,否则返回false。

并且test()方法经常被用在if语句中,举例如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Regular Expression</title>
</head>
<body>
    <input type="text" id="phoneNumber">
    <button id="submit">提交</button>
    <script>
    window.onload=function(){
        var btn=document.getElementById("submit");
        btn.onclick=function(){
            var phoneNumber=document.getElementById("phoneNumber").value;
            var pattern=/1[358]\d{9}/gi;
            if(pattern.test(phoneNumber)){
                alert("Yes! Your phoneNumber is legal");
            }else{
                alert("No!Your phoneNumber is illegal");
            }
        }
    }
    </script>
</body>
</html>
6.4.3 RegExp实例的toString()和toLocalString()方法

这两个方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。
举例如下:

var pattern=/1[358]\d{9}/gi;
console.log(pattern.toString());
console.log(pattern.toLocaleString());

6.5 RegExp的构造函数属性

RegExp构造函数也包含了一些属性。值得注意的是,这些属性有两种方式来访问---长属性名和短属性名。介绍如下:

  1. input $_ 最近一次要匹配的字符串 。(注意:前者是长属性名,后者是短属性名,下同)
  2. lastMatch $& 最近一次的匹配向。
  3. lastParen $+ 最近一次匹配的捕获组。
  4. leftContext $` input字符串中lastMatch之前的文本
  5. RightContext $' input字符串中lastMatch之后的文本
  6. multiline $* 布尔值,表示是否所有表达式都使用多行模式

注意:Opera不支持上面的1236对应的四个属性,IE不支持multiline属性。

举例如下所示:

var text="this has been a short summer";
    var pattern=/(.)hort/g;
    if(pattern.test(text)){
        console.log(RegExp.input);//this has been a short summer
        console.log(RegExp.leftContext);//this has been a 
        console.log(RegExp.rightContext);//summer
        console.log(RegExp.lastParen);//s
        console.log(RegExp.lastMatch);//short
        console.log(RegExp.multiline);//undefined
    }

  1. abc
  2. a-z

已注销
222 声望52 粉丝

机械男,程序员,前军校学员,穷逼博士,非著名高校青椒。。。